Amazon SNS でプライベートエンドポイントに メッセージを送信してみた
はじめに
アノテーション株式会社の hato です。
Amazon SNS から HTTP または HTTPS エンドポイントに送信されるメッセージは、パブリック IP アドレスが送信元となるため、プライベートエンドポイント(プライベートサブネット内のエンドポイント)にメッセージを送信したい場合は、 Lambda 関数などを経由する必要があります。
Lambda 関数を利用する方法は AWS ナレッジセンターにて公開されていますが、実際に構築したことはなかったのと、お問い合わせ頂いた際に備えて画面キャプチャを取得するため、やってみました。
なお、プライベートサブネット内から Amazon SNS にメッセージを送信する方法は次のブログとなります。
やってみた
前提
- SNS トピックは作成済
- メッセージ受信用にプライベートサブネットに EC2 を作成、受信アプリ配置済み
構成イメージ
手順
- セキュリティグループの作成
- IAM ロールの作成
- Lambda 関数のコード作成
- Lambda 関数の作成
- SNS トピックの作成
- テスト
セキュリティグループの作成
Lambda 関数に設定するセキュリティグループを作成します。
Amazon VPC コンソール のナビゲーションペインから「セキュリティグループ」を選択して、「セキュリティグループを作成」を選択します。
次の値を指定して「セキュリティグループを作成」を選択します。
- セキュリティグループ名:任意の名前(例:
LambdaSG
) - VPC:プライベートエンドポイントの VPC
セキュリティグループが正常に作成されたことを確認します。
IAM ロールの作成
Lambda に設定する IAM ロールを作成します。
VPC に接続する Lambda は通常の Lambda 関数の権限に加えて、追加の権限が必要となります。
今回は必要な権限をまとめた AWS 管理ポリシーAWSLambdaVPCAccessExecutionRole
を使用します。
IAM コンソール を開き、ロールから「ロールを作成」をクリックします。
信頼されたエンティティタイプに「AWS のサービス」、ユースケースに「Lambda」を選択して、「次へ」をクリックします。
許可ポリシーからAWSLambdaVPCAccessExecutionRole
を選択して、「次へ」をクリックします。
ロール名に任意の名前(例:lambda_vpc_basic_execution
)を指定して、「ロールを作成」をクリックします。
IAM ロールが正常に作成されたことを確認します。
Lambda 関数のコード作成
Amazon SNS をトリガーに Lambda 関数が実行された場合に、プライベートエンドポイントにリクエストを送信するサンプルコードを作成します。
作業用のディレクトリを作成します。
$ mkdir my-sourcecode-function $ cd my-sourcecode-function
エディタで次のサンプルコードを作成します。
※5行目はプライベートエンドポイントの URL に修正してください。
import json import requests def lambda_handler(event, context): url = "<PRIVATE_HTTP/S_ENDPOINT_URL>" sns_message_payload = event["Records"][0]["Sns"] sns_message_headers = { "x-amz-sns-message-id": sns_message_payload['MessageId'], "x-amz-sns-message-type": sns_message_payload["Type"], "x-amz-sns-subscription-arn" : event["Records"][0]["EventSubscriptionArn"], "x-amz-sns-topic-arn" : sns_message_payload["TopicArn"] } try: r = requests.post(url = url, data = json.dumps(sns_message_payload), headers = sns_message_headers) except Exceptions as e: print(e) print(r.content) return { 'statusCode': 200, 'body': json.dumps(r.content) }
pip
で周辺モジュールをインストールして、ZIP圧縮します。
$ pip install --target ./package requests ...(中略)... Successfully installed certifi-2022.12.7 charset-normalizer-2.1.1 idna-3.4 requests-2.28.1 urllib3-1.26.13 $ cd package $ zip -r ../my-deployment-package.zip . ...(中略)... adding: urllib3/poolmanager.py (deflated 71%) adding: urllib3/_collections.py (deflated 69%) $ cd .. $ zip -g my-deployment-package.zip lambda_function.py adding: lambda_function.py (deflated 75%)
Lambda 関数の作成
プライベートエンドポイントにリクエストを送信する Lambda 関数を作成します。
Lambda コンソールを開き、関数から「関数の作成」をクリックします。
次の値を指定し、「▼詳細設定」を選択します。
- 関数名:任意の名前(例:
Private-endpoint-Amazon-SNS-topic-subscription
) - ランタイム:Python 3.8
- デフォルトの実行ロールの変更:
既存のロールを使用する
- 作成した IAM ロールを指定(例:
lambda_vpc_basic_execution
)
- 作成した IAM ロールを指定(例:
次の値を指定して「関数の作成」を選択します。
- VPC を有効化:有効
- VPC:プライベートエンドポイントの VPC
- サブネット:プライベートサブネットを指定
- セキュリティグループ:作成したセキュリティグループを指定(例:
LambdaSG
)
Lambda 関数の作成中は設定変更ができないためしばらく待ちます。
Lambda 関数が正常に作成されたことを確認します。
作成したサンプルコードを設定します。 「アップロード元」から「.zipファイル」を選択
手順3で作成したサンプルコード(ZIP)を選択します。
コード変更の警告です。「OK」を選択します。
次の手順で必要になるため Lambda 関数の ARN をメモします。
エンドポイントのサブスクライブ
Amazon SNS コンソール のナビゲーションペインから「サブスクリプションの作成」を選択します。
次の値を指定して「サブスクリプションの作成」を選択します。
- トピック ARN:関連付けを行う SNS トピックを選択
- プロトコル:
AWS Lambda
- エンドポイント:Lambda 関数の ARN を指定
サブスクリプションが正常に作成されたことを確認します。
メッセージの通知確認
「メッセージの発行」を選択します。
テストメッセージを入力して「メッセージの発行」を選択します。
エンドポイントにメッセージが配信されました。
{ "Type": "Notification", "MessageId" : "22b80b92-fdea-4c2c-8f9d-bdfb0c7bf324", "TopicArn" : "arn:aws:sns:ap-northeast-1:123456789012:hato-sns-topic", "Subject": "hato-test-title", "Message": "hato-test-Message", "Timestamp" : "2012-05-02T00:54:06.655Z", "SignatureVersion": "1", "Signature" : "EXAMPLEw6JRN...", "SigningCertURL" : "https://sns.ap-northeast-1.amazonaws.com/SimpleNotificationService-f3ecfb7224c7233fe7bb5f59f96de52f.pem", "UnsubscribeURL" : "https://sns.ap-northeast-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:ap-northeast-1:123456789012:hato-sns-topic:d6a4f408-4021-4e66-82e3-920cb71bb5fe" "MessageAttributes": {} }
最後に
この記事が誰かのお役にたてば幸いです。
参考資料
- プライベートエンドポイントを Amazon SNS トピックにサブスクライブする
- Amazon SNS の IP アドレス範囲を取得する
- Deploy Python Lambda functions with .zip file archives - AWS Lambda
- 同じアカウントで Lambda 関数を Amazon SNS のトピックにサブスクライブする
アノテーション株式会社について
アノテーション株式会社は、クラスメソッド社のグループ企業として「オペレーション・エクセレンス」を担える企業を目指してチャレンジを続けています。「らしく働く、らしく生きる」のスローガンを掲げ、様々な背景をもつ多様なメンバーが自由度の高い働き方を通してお客様へサービスを提供し続けてきました。現在当社では一緒に会社を盛り上げていただけるメンバーを募集中です。少しでもご興味あれば、アノテーション株式会社WEBサイトをご覧ください。